﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary
{
    /// <summary>
    /// Provides methods to deal with the Fibonacci sequence.
    /// </summary>
    [Serializable]
    public static class Fibonacci
    {
        /// <summary>
        /// Computes the nth Fibonaccinumber.
        /// </summary>
        /// <param name="n">The index of the number in the Fibonacci sequence.</param>
        /// <returns>A long integer that equals the nth Fibonacci number.</returns>
        public static UInt64 ComputeFibonacciNumber(uint n)
        {
            return (UInt64) (1 / Math.Sqrt(5) * ((Math.Pow((1 + Math.Sqrt(5)) / 2, n))
                                                 - (Math.Pow((1 - Math.Sqrt(5)) / 2, n))));
        }

        /// <summary>
        /// Computes the nth Fibonaccinumber by approximation.
        /// </summary>
        /// <param name="n">The index of the number in the Fibonacci sequence.</param>
        /// <returns>A long integer that equals the nth Fibonacci number.</returns>
        public static UInt64 ComputeFibonacciNumberByApproximation(uint n)
        {
            return (UInt64) Math.Floor(1 / Math.Sqrt(5) * (Math.Pow((1 + Math.Sqrt(5)) / 2, n) + 0.5));
        }

        /// <summary>
        /// Generates an array of Fibonacci numbers.
        /// </summary>
        /// <param name="seek">The border, to which the Fibonacci numbers should be generated.</param>
        /// <returns>The generated Fibonacci numbers.</returns>
        public static UInt64[] GenerateFibonacciNumbers(uint seek)
        {
            uint i = 1;
            UInt64 lastNumber = 1;
            List<UInt64> result = new List<UInt64>();

            while (lastNumber < seek)
            {
                lastNumber = Fibonacci.ComputeFibonacciNumber(i);

                if (lastNumber < seek)
                {
                    result.Add(lastNumber);
                }

                i++;
            }

            return result.ToArray();
        }
    }
}